// GetTcpTable.cpp : Defines the entry point for the console application.
//

// Link to Ws2_32.lib
//#include <winsock2.h>
#include <ws2tcpip.h>
// Link to Iphlpapi.lib
#include <iphlpapi.h>
#include <stdio.h>
#include <tchar.h>
#include <m_core.h>
#include "netstat.h"
// Note: could also use malloc() and free()
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
 
struct CONNECTION* GetConnectionsTable()
{
    // Declare and initialize variables
    MIB_TCPTABLE_OWNER_PID *pTcpTable;
    DWORD dwSize = 0;
    DWORD dwRetVal = 0;
    struct in_addr IpAddr;
    int i;
	struct CONNECTION *connHead=NULL;

    pTcpTable = (MIB_TCPTABLE_OWNER_PID *) MALLOC(sizeof (MIB_TCPTABLE_OWNER_PID));
    if (pTcpTable == NULL)
    {
        //printf("Error allocating memory!\n");
        return NULL;
    }
 
    dwSize = sizeof (MIB_TCPTABLE_OWNER_PID);
    // Make an initial call to GetTcpTable to
    // get the necessary size into the dwSize variable
    if ((dwRetVal = GetExtendedTcpTable(pTcpTable, &dwSize, TRUE,AF_INET,TCP_TABLE_OWNER_PID_ALL,0)) ==  ERROR_INSUFFICIENT_BUFFER)
    {
        FREE(pTcpTable);
        pTcpTable = (MIB_TCPTABLE_OWNER_PID *) MALLOC(dwSize);
        if (pTcpTable == NULL)
        {
            //printf("Error allocating memory\n");
            return NULL;
        }
    }
 
    // Make a second call to GetTcpTable to get
    // the actual data we require
    if ((dwRetVal = GetExtendedTcpTable(pTcpTable, &dwSize, TRUE,AF_INET,TCP_TABLE_OWNER_PID_ALL,0)) == NO_ERROR)
    {
        //printf("\tLocal Addr\tLocal Port\tRemote Addr\tRemote Port\n");
        //printf("Number of entries: %d\n", (int) pTcpTable->dwNumEntries);
		

        for (i = 0; i < (int) pTcpTable->dwNumEntries; i++)
        {
			struct CONNECTION* newConn=(struct CONNECTION*)mir_alloc(sizeof(struct CONNECTION));
			memset(newConn,0,sizeof(struct CONNECTION));
			//pid2name(pTcpTable->table[i].dwOwningPid,&newConn->Pname);
			
			if(pTcpTable->table[i].dwLocalAddr)
			{
				IpAddr.S_un.S_addr = (ULONG) pTcpTable->table[i].dwLocalAddr;
				//_snprintf(newConn->strIntIp,_countof(newConn->strIntIp),"%d.%d.%d.%d",IpAddr.S_un.S_un_b.s_b1,IpAddr.S_un.S_un_b.s_b2,IpAddr.S_un.S_un_b.s_b3,IpAddr.S_un.S_un_b.s_b4);
				wcsncpy(newConn->strIntIp, mir_a2t(inet_ntoa(IpAddr)),_tcslen(mir_a2t(inet_ntoa(IpAddr))));
			}
			
			if(pTcpTable->table[i].dwRemoteAddr)
			{
				IpAddr.S_un.S_addr = (u_long) pTcpTable->table[i].dwRemoteAddr;
				wcsncpy(newConn->strExtIp, mir_a2t(inet_ntoa(IpAddr)),_tcslen(mir_a2t(inet_ntoa(IpAddr))));
			}
            newConn->state = pTcpTable->table[i].dwState;
			newConn->intIntPort =ntohs((u_short)pTcpTable->table[i].dwLocalPort);
			newConn->intExtPort =ntohs((u_short)pTcpTable->table[i].dwRemotePort);
			newConn->Pid=pTcpTable->table[i].dwOwningPid;
			
			switch (pTcpTable->table[i].dwState)
            {
            case MIB_TCP_STATE_CLOSED:
                //printf("CLOSED\n");
                break;
            case MIB_TCP_STATE_LISTEN:
                //printf("LISTEN\n");
                break;
            case MIB_TCP_STATE_SYN_SENT:
                //printf("SYN-SENT\n");
                break;
            case MIB_TCP_STATE_SYN_RCVD:
                //printf("SYN-RECEIVED\n");
                break;
            case MIB_TCP_STATE_ESTAB:
                //printf("ESTABLISHED\n");
                break;
            case MIB_TCP_STATE_FIN_WAIT1:
                //printf("FIN-WAIT-1\n");
                break;
            case MIB_TCP_STATE_FIN_WAIT2:
                //printf("FIN-WAIT-2 \n");
                break;
            case MIB_TCP_STATE_CLOSE_WAIT:
                //printf("CLOSE-WAIT\n");
                break;
            case MIB_TCP_STATE_CLOSING:
                //printf("CLOSING\n");
                break;
            case MIB_TCP_STATE_LAST_ACK:
                //printf("LAST-ACK\n");
                break;
            case MIB_TCP_STATE_TIME_WAIT:
                //printf("TIME-WAIT\n");
                break;
            case MIB_TCP_STATE_DELETE_TCB:
                //printf("DELETE-TCB\n");
                break;
            default:
                //printf("UNKNOWN dwState value\n");
                break;
            }
			newConn->next = connHead;
			connHead=newConn;
 
          //printf("TCP[%d]:%s%15d%20s%15d\n", i, szLocalAddr,ntohs((u_short)pTcpTable->table[i].dwLocalPort), szRemoteAddr,ntohs((u_short)pTcpTable->table[i].dwRemotePort));
 
            //printf("\tTCP[%d] Local Addr: %s\n", i, szLocalAddr);
            // printf("\tTCP[%d] Local Port: %d \n", i, ntohs((u_short)pTcpTable->table[i].dwLocalPort));
            //printf("\tTCP[%d] Remote Addr: %s\n", i, szRemoteAddr);
            //printf("\tTCP[%d] Remote Port: %d\n", i, ntohs((u_short)pTcpTable->table[i].dwRemotePort));
        }
   }
   else
   {
        //printf("\tGetTcpTable() failed with return value %d\n", dwRetVal);
        FREE(pTcpTable);
        return NULL;
    }
	if (pTcpTable != NULL) 
	{
        FREE(pTcpTable);
        pTcpTable = NULL;
    } 
    return connHead;
}

void deleteConnectionsTable(struct CONNECTION* head)
{
	struct CONNECTION *cur=head,*del;
	while(cur!=NULL)
	{	
		del=cur;
		cur=cur->next;
		mir_free(del);
		head=cur;
	}
	head=NULL;
}

struct CONNECTION* searchConnection(struct CONNECTION* head,TCHAR *intIp,TCHAR *extIp,int intPort,int extPort,int state)
{
	struct CONNECTION *cur=head;
	while(cur!=NULL)
	{
		if(wcscmp(cur->strIntIp,intIp)==0 && wcscmp(cur->strExtIp,extIp)==0 && cur->intExtPort==extPort && cur->intIntPort==intPort && cur->state==state)
			return cur;
		cur=cur->next;
	}
	return NULL;
}

void getDnsName(TCHAR *strIp,TCHAR *strHostName)
{
	struct in_addr iaHost;
	struct hostent *h;

	iaHost.s_addr = inet_addr(mir_t2a(strIp));
	if ((h = gethostbyaddr ((char *)&iaHost, sizeof(struct in_addr), AF_INET))== NULL)
		{  // get the host info error
			_stprintf(strHostName,_T("%s"), strIp);
            return;
        }
	_stprintf(strHostName,_T("%s"),mir_a2t(h->h_name));
	//_tcsncpy_s(strHostName,128, h->h_name,_tcslen(h->h_name));

}

int wildcmp(const TCHAR *wild, const TCHAR *string) {
  // Written by Jack Handy - jakkhandy@hotmail.com

  const TCHAR *cp = NULL, *mp = NULL;

  while ((*string) && (*wild != '*')) {
    if ((*wild != *string) && (*wild != '?')) {
      return 0;
    }
    wild++;
    string++;
  }

  while (*string) {
    if (*wild == '*') {
      if (!*++wild) {
        return 1;
      }
      mp = wild;
      cp = string+1;
    } else if ((*wild == *string) || (*wild == '?')) {
      wild++;
      string++;
    } else {
      wild = mp;
      string = cp++;
    }
  }

  while (*wild == '*') {
    wild++;
  }
  return !*wild;
}
